﻿#include <iostream>               // 标准输入输出流
#include <vector>                 // 向量容器
#include <thread>                 // 线程库
#include <queue>                  // 队列容器
#include <mutex>                  // 互斥锁
#include <condition_variable>    // 条件变量
#include <functional>             // 函数包装器（std::function、std::bind）
#include <future>                 // 异步操作和未来（std::future、std::packaged_task）
#include <atomic>                 // 原子操作（std::atomic）

// 线程池类定义
class ThreadPool {
public:
    ThreadPool(size_t threadCount);  // 构造函数，传入线程数量
    ~ThreadPool();                   // 析构函数，释放资源

    // 任务入队函数模板，返回任务执行结果的future
    template<typename Func, typename... Args>
    auto enqueue(Func&& f, Args&&... args)
    -> std::future<typename std::result_of<Func(Args...)>::type>;

private:
    void worker();  // 工作线程执行函数

    std::vector<std::thread> workers;             // 存放工作线程的容器
    std::queue<std::function<void()>> tasks;      // 任务队列，存放无参无返回值的函数对象

    std::mutex queueMutex;                         // 保护任务队列的互斥锁
    std::condition_variable condition;             // 任务到达或线程池停止的条件变量
    std::atomic<bool> stop;                         // 是否停止线程池的标志，原子类型，防止竞态
};

// 构造函数，创建指定数量的线程，线程入口函数是worker成员函数
ThreadPool::ThreadPool(size_t threadCount) : stop(false) {
    for (size_t i = 0; i < threadCount; ++i) {
        // 创建线程，线程执行lambda捕获this指针，调用worker成员函数
        workers.emplace_back([this] { this->worker(); });
    }
}

// 析构函数，停止线程池，等待所有线程结束
ThreadPool::~ThreadPool() {
    stop = true;                // 设置停止标志为true
    condition.notify_all();     // 通知所有等待的线程唤醒
    for (auto& worker : workers) {
        if (worker.joinable())  // 判断线程是否可以join（未被join或detach）
            worker.join();      // 等待线程执行结束
    }
}

// 工作线程循环函数，不断从任务队列取任务执行
void ThreadPool::worker() {
    while (!stop) {  // 当线程池未停止时循环
        std::function<void()> task;
        {
            std::unique_lock<std::mutex> lock(queueMutex);  // 加锁保护任务队列
            // 等待条件变量，条件是停止或任务队列非空
            condition.wait(lock, [this] { return stop || !tasks.empty(); });
            if (stop && tasks.empty())  // 如果停止且任务已处理完，退出线程函数
                return;
            task = std::move(tasks.front());  // 取出队首任务（右值引用移动）
            tasks.pop();                      // 弹出队首任务
        }
        task();  // 执行任务函数
    }
}

// 任务入队函数模板，传入任意可调用对象和参数，返回对应类型的future
template<typename Func, typename... Args>
auto ThreadPool::enqueue(Func&& f, Args&&... args)
-> std::future<typename std::result_of<Func(Args...)>::type>
{
    using return_type = typename std::result_of<Func(Args...)>::type;  // 推断任务返回类型

    // 创建一个打包任务，用std::bind绑定传入的函数和参数
    auto taskPtr = std::make_shared<std::packaged_task<return_type()>>(
            std::bind(std::forward<Func>(f), std::forward<Args>(args)...)
    );

    std::future<return_type> res = taskPtr->get_future();  // 获取任务的future，用于后续获取结果
    {
        std::lock_guard<std::mutex> lock(queueMutex);     // 加锁保护任务队列
        if (stop)                                         // 如果线程池已停止，抛异常
            throw std::runtime_error("enqueue on stopped ThreadPool");

        // 把任务包装成无参void函数，放入任务队列
        tasks.emplace([taskPtr]() { (*taskPtr)(); });
    }
    condition.notify_one();  // 通知一个等待线程有新任务
    return res;              // 返回future对象
}

int main() {
    ThreadPool pool(4);  // 创建含4个线程的线程池
    // 往线程池添加任务，计算两个数相加，模拟耗时1秒
    auto f1 = pool.enqueue([](int a, int b) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        return a + b;
    }, 3, 7);

    // 添加另一个任务，打印一条消息
    auto f2 = pool.enqueue([]() {
        std::cout << "Hello from thread pool!" << std::endl;
    });
    // 主线程等待f1任务完成并输出结果
    std::cout << "Result of f1: " << f1.get() << std::endl;
    // 等待一段时间，确保线程池中的任务执行完毕
    std::this_thread::sleep_for(std::chrono::seconds(2));

    return 0;
}
